package icegps.com.pingdj.data.analysis;


import com.clj.fastble.utils.HexUtil;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;

import icegps.com.pingdj.bean.LocationStatus;
import icegps.com.pingdj.bean.SatelliteData;
import icegps.com.pingdj.constant.Constant;
import timber.log.Timber;

import static icegps.com.pingdj.map.utils.LatAndLot2Coord.D2R;

/**
 * Created by 111 on 2017/12/23.
 */

public class AnalysisHex {

    private int pos = 0;
    private int dataSumLenght = 0;
    private static ByteBuffer b;

    private final LocationStatus locationStatus;

    public AnalysisHex() {
        locationStatus = new LocationStatus();
        b = ByteBuffer.allocate(256);
        b.order(ByteOrder.LITTLE_ENDIAN);//小

    }

    public boolean isAdd() {
        return pos != 0;
    }


    public synchronized void analysisData(byte bt) {
        if (pos == 0) {
            if (b.get(0) == Constant.head1 && bt == Constant.head2) {
                b.put(1, Constant.head2);
                pos = 2;
            } else {
                b.put(0, bt);
            }
        } else {
            b.put(pos++, bt);
            if (pos == 6) {
                dataSumLenght = Integer.parseInt(HexUtil.formatHexString(new byte[]{b.get(5), b.get(4)}), 16) + 8;
                if (dataSumLenght > 256) {
                    pos = 0;
                }
            }
            if (pos == dataSumLenght) {
                pos = 0;
                boolean checksum = checksum(b, dataSumLenght);
                if (checksum) {
                    getData();
                }
            }
        }
    }

    private void getData() {
        int q = 0;
        // header
        q += 2;
        // class
        byte dataClass = AnalysisHex.b.get(q);
        q++;
        // ID
        byte dataId = AnalysisHex.b.get(q);
        q++;
        // lengthIndex
        q += 2;
        if (dataClass == Constant.locationDataClass && dataId == Constant.locationDataId) {
            getLocationData(q);
        } else if (dataClass == Constant.satelliteDataClass && dataId == Constant.satelliteDataId) {
            getSatelliteData(q);
        }
    }


    private void getLocationData(int q) {
        //日期 int
        locationStatus.setDate(AnalysisHex.b.getInt(q));
        q += 4;

        //时间 int
        locationStatus.setMillis(AnalysisHex.b.getInt(q) / 1000d);
        q += 4;

        //纬度 double
        locationStatus.setLatitude(AnalysisHex.b.getDouble(q));
        q += 8;

        //经度 double
        locationStatus.setLongitude(AnalysisHex.b.getDouble(q));
        q += 8;

        // 海拔 double
        locationStatus.setAltitude(AnalysisHex.b.getDouble(q));
        q += 8;

        //航向角 int
        locationStatus.setCourseAngle(b.getInt(q) / 1000f);
        q += 4;

        //速度 int
        locationStatus.setSpeed(b.getInt(q) / 1000f);
        q += 4;

        //卫星数 int
        locationStatus.setSatelliteSum(AnalysisHex.b.get(q));
        q += 1;

        //定位状态 byte
        locationStatus.setStatus(AnalysisHex.b.get(q));
        q += 1;

        //延时 int
        locationStatus.setDelay(AnalysisHex.b.getFloat(q));
        q += 4;

        //基线长度 int
        locationStatus.setDistance(AnalysisHex.b.getInt(q) / 1000d);
        q += 4;

        //方位角 int
        locationStatus.setAzimuth(AnalysisHex.b.getInt(q) / 1000d);
        q += 4;

        //仰角 int
        locationStatus.setElevation(AnalysisHex.b.getInt(q) / 1000d);


        double v = locationStatus.getAltitude() + locationStatus.getDistance() * Math.sin(locationStatus.getElevation() * D2R);

        locationStatus.setAltitude2(v);
        locationStatus.setDispersion(locationStatus.getDistance() * Math.sin(locationStatus.getElevation() * (Math.PI / 180)));
        if (onHexDataListener != null) {
            onHexDataListener.onLocationData(locationStatus);
        }
    }


    ArrayList<SatelliteData> satelliteDatas = new ArrayList<>();

    private void getSatelliteData(int q) {
        satelliteDatas.clear();
        byte satelliteType = AnalysisHex.b.get(q);
        q += 1;
        byte count = b.get(q);
        q += 1;
        for (byte i = 0; i < count; i++) {
            SatelliteData satelliteData = new SatelliteData();
            satelliteData.setSatelliteType(satelliteType);
            satelliteData.setSatelliteNumber(b.get(q));
            q += 1;
            satelliteData.setSatelliteUseSign(b.get(q));
            q += 1;
            satelliteData.setSatelliteElevation(b.get(q));
            q += 1;
            satelliteData.setSatelliteAzimuth(AnalysisHex.b.getShort(q));
            q += 2;
            satelliteData.setSatelliteSNR(AnalysisHex.b.get(q));
            q += 1;
            satelliteDatas.add(satelliteData);

        }
        ArrayList<SatelliteData> satellites = new ArrayList<>();

        satellites.addAll(satelliteDatas);

        if (onHexDataListener != null) {
            onHexDataListener.onSatelliteData(satellites, satelliteType);
        }
    }

    OnHexDataListener onHexDataListener;

    public interface OnHexDataListener {

        void onLocationData(LocationStatus locationStatus);

        void onSatelliteData(ArrayList<SatelliteData> satelliteDatas, byte type);
    }

    public void setOnHexDataListener(OnHexDataListener onHexDataListener) {
        this.onHexDataListener = onHexDataListener;
    }


    static boolean checksum(ByteBuffer buff, int len) {
        int cka = 0, ckb = 0;
        int i;
        for (i = 2; i < len - 2; i++) {
            cka += (int) buff.get(i) & 0x000000FF;
            cka = cka & 0x000000FF;
            ckb += cka;
            ckb = ckb & 0x000000FF;
        }
        return cka == ((int) buff.get(len - 2) & 0x000000FF) && ckb == ((int) buff.get(len - 1) & 0x000000FF);
    }


}
